﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BZV.Foundation;
using System.Collections;

namespace BZV.Foundation.Business
{
    // 彩票预测器，根据数据的特点预测以后几期彩票，数据池中的数据至少有100条
    // 走势好的提示，每期的结果预测
    public class LotteryComPerdictor
    {
        // 常变量
        public static double STABLESIX_FREQ = 0.72;
        public static double STABLETHREE_FREQ = 0.27;
        public static double STABLEALL_FREQ = 0.01;
        public static int STABLE_PERIOD = 100;

        // 周期信息
        Dictionary<CombinationState, PeriodInfo> m_Periods;             // 当前使用的周期参数

        // 数据池
        private List<Lottery> m_lotterys;

        /// <summary>
        /// 构造函数
        /// </summary>
        public LotteryComPerdictor()
        {
            // 初始化周期参数
            m_Periods = new Dictionary<CombinationState, PeriodInfo>();
            m_Periods[CombinationState.EN_COM_SIX] = new PeriodInfo(STABLESIX_FREQ, 0);
            m_Periods[CombinationState.EN_COM_THREE] = new PeriodInfo(STABLETHREE_FREQ, 0);
            m_Periods[CombinationState.EN_COM_ALL] = new PeriodInfo(STABLEALL_FREQ, 0);

            // 
        }

        /// <summary>
        /// 设置数据池
        /// </summary>
        /// <param name="pool"></param>
        public void SetData(List<Lottery> loterys)
        {
            m_lotterys = loterys;
        }

#region 基本类型的计算
        /// <summary>
        /// 获取当前位置以前nIndex以前的数值个数参数（包含当前位置）
        /// </summary>
        /// <param name="nIndex"></param>
        /// <param name="lenght"></param>
        /// <returns></returns>
        public ThreeNumerialParam GetNumerialParam(int nIndex, int lenght = 100)
        {
            ThreeNumerialParam param = new ThreeNumerialParam();
            param.nCount = lenght;
            for (int i = nIndex + lenght - 1; i >= nIndex; i--)
            {
                Lottery lot = m_lotterys[i];
                for (int j = 2; j <= 4; j++)
                {
                    int nNo = Convert.ToInt32(lot.Code[j].ToString());
                    param.PerCount[nNo]++;
                }
            }

            return param;
        }

        /// <summary>
        /// 预测, 只能预测不会给出相应的概率
        /// </summary>
        /// <param name="nStartIndex">预测的位置</param>
        /// <param name="lenght">长度</param>
        /// <param name="isDelPost">是否要去掉先验值</param>
        /// <returns></returns>
        public UintParam ForecastRange(int nStartIndex, int lenght, bool isDelPost = true)
        {
//             // 计算当前
//             int nPeriod = STABLE_PERIOD;
// 
//             // 计算最新的参数
//             UintParam newParam = GetUintIndex(nStartIndex, nPeriod - lenght);
//             int nThree = (int)(nPeriod * m_Periods[CombinationState.EN_COM_THREE].dTotalPeriod) - newParam.CombinationCount[CombinationState.EN_COM_THREE];
//             int nSix = (int)(nPeriod * m_Periods[CombinationState.EN_COM_SIX].dTotalPeriod) - newParam.CombinationCount[CombinationState.EN_COM_SIX];
//             int nAll = (int)(nPeriod * m_Periods[CombinationState.EN_COM_ALL].dTotalPeriod) - newParam.CombinationCount[CombinationState.EN_COM_ALL];
// 
//             // 剔除先验数据 lenght个数据
//             if (isDelPost)
//             {
//                 for (int i = 0; i < nStartIndex; i++)
//                 {
//                     Lottery lottery = m_lotterys[i];
//                     if (lottery.Param.comState == CombinationState.EN_COM_SIX)
//                     {
//                         nSix--;
//                     }
//                     else if (lottery.Param.comState == CombinationState.EN_COM_THREE)
//                     {
//                         nThree--;
//                     }
//                     else if (lottery.Param.comState == CombinationState.EN_COM_ALL)
//                     {
//                         nAll--;
//                     }
//                 }
//             }
// 
//             // 得到分布
//             UintParam forcast = new UintParam(nSix, nThree, nAll);
// 
// 
            return null;
        }


#endregion

#region 组六预测
        /// <summary>
        /// 预测组态 5-10
        /// </summary>
        public int[] ForecastCombinSix(int nIndex)
        {
            // 创建分析器
            Analyzer analyzer = new Analyzer();
            analyzer.SetData(m_lotterys);
            int nTotal = 0;
            int nCorrent = 0;
            int[] arr = ForecastCombinSixBy20(analyzer, nIndex);
            return arr;
            for (int i = 20000; i > 0; i--)
            {
                double d = ForecastCombinSixByThreeToSix(analyzer, i);
                Lottery cur = m_lotterys[i - 1];
                if (d == 1 && cur.Param.comState == CombinationState.EN_COM_SIX)
                {
                    nCorrent++;
                }
                else if (d == 0 && cur.Param.comState != CombinationState.EN_COM_SIX)
                {
                    nCorrent++;
                }

                if (d == 0 || d == 1)
                {
                    nTotal++;
                }
            }
            
        }

        /// <summary>
        /// 组态不同转换矩阵预测， 返回0-一定不会组六，1-一定为组六，-1---无法判断
        /// </summary>
        /// <param name="analyzer"></param>
        /// <param name="nIndex">指定的位置开始</param>
        /// <returns></returns>
        public double ForecastCombinSixByThreeToSix(Analyzer analyzer, int nIndex = 0)
        {
            // 预测需要的参数
            int nSixCount = 0;
            int nThreeCount = 0;

            // 得到当前的情况
            CombinationState curCombinState = CombinationState.EN_COM_SIX;
            bool bIsSame = false;
            for (int i = nIndex; i < m_lotterys.Count; i++)
            {
                if (i == nIndex)
                {
                    curCombinState = m_lotterys[i].Param.comState;
                    if (curCombinState == CombinationState.EN_COM_ALL)
                    {
                        curCombinState = CombinationState.EN_COM_THREE;
                    }
                    bIsSame = true;
                    if (curCombinState == CombinationState.EN_COM_SIX)
                    {
                        nSixCount++;
                    }
                    else
                    {
                        nThreeCount++;
                    }
                    continue;
                }

                Lottery lot = m_lotterys[i];
                if (lot.Param.comState == curCombinState)
                {
                    if (!bIsSame)               // 说明已经完成了
                    {
                        break;
                    }

                    if (curCombinState == CombinationState.EN_COM_SIX)
                    {
                        nSixCount++;
                    }
                    else
                    {
                        nThreeCount++;
                    }
                    bIsSame = true;
                }
                else
                {
                    if (lot.Param.comState == CombinationState.EN_COM_SIX)
                    {
                        nSixCount++;
                    }
                    else
                    {
                        nThreeCount++;
                    }
                    bIsSame = false;
                }
            }

            // 开始预测
            int nCurCount = 0;
            if (curCombinState == CombinationState.EN_COM_SIX)          // 上一个则是组三或豹子
            {
                int nTotal = 0;
                int[] arr = new int[analyzer.CombinThreeToSix.GetLength(1)];
                for (int i = 0; i < analyzer.CombinThreeToSix.GetLength(1); i++)
                {
                    arr[i] = analyzer.CombinThreeToSix[nThreeCount, i];
                }
                int[] result = Analyzer.GetBestRange(arr, 0.95);
                if (result == null)
                {
                    return -1;
                }

                
                //if (nSixCount + 1 > result[1] || nSixCount + 1 < result[0])
                {
                    if (analyzer.CombinThreeToSix[nThreeCount, nSixCount + 1] < 1)
                    {
                        return 0;
                    }
                }
            }
            else                                // 组六
            {
                int nTotal = 0;
                int[] arr = new int[analyzer.CombinSixToThree.GetLength(1)];
                for (int i = 0; i < analyzer.CombinSixToThree.GetLength(1); i++)
                {
                    arr[i] = analyzer.CombinSixToThree[nSixCount, i];
                }
                int[] result = Analyzer.GetBestRange(arr, 0.95);
                if (result == null)
                {
                    return -1;
                }
                //if (nThreeCount + 1 > result[1] || nThreeCount + 1 < result[0])
                {
                    if (analyzer.CombinSixToThree[nSixCount, nThreeCount + 1] < 1)
                    {
                        return 1;
                    }
                    
                }
            }

            return -1;
        }

        /// <summary>
        /// 从当前位置开始的后20个开始预测
        /// </summary>
        /// <param name="analyzer"></param>
        /// <param name="nIndex"></param>
        /// <returns></returns>
        public int[] ForecastCombinSixBy20(Analyzer analyzer, int nIndex = 0)
        {
            // 获取前前20个
            UintParam lastParam = analyzer.GetUintIndex(nIndex + 20 + 15);
            UintParam curParam = analyzer.GetUintIndex(nIndex + 15);

            // 二阶预测
            int[] arr = new int[analyzer.CombinSixToSix3.GetLength(2)];
            for (int i = 0; i < analyzer.CombinSixToSix3.GetLength(2); i++)
            {
                arr[i] = analyzer.CombinSixToSix3[lastParam.CombinationCount[CombinationState.EN_COM_SIX],
                curParam.CombinationCount[CombinationState.EN_COM_SIX], i];
            }
            double d = analyzer.CombinSixToSix[lastParam.CombinationCount[CombinationState.EN_COM_SIX],
                curParam.CombinationCount[CombinationState.EN_COM_SIX]];
            return arr;
        }
#endregion

#region 数字预测
        public int[] ForecastNum(int nIndex, int nNo)
        {
            Analyzer anlyzer = new Analyzer();
            anlyzer.SetData(m_lotterys);

            int[] arr = anlyzer.GetNumCount(nIndex + 15);
            int[] lastarr = anlyzer.GetNumCount(nIndex + 20 + 15);
            int[, ,] data = anlyzer.TwoToTwo3[nNo];


            int[] result = new int[data.GetLength(2)];
            for (int i = 0; i < data.GetLength(2); i++)
            {
                result[i] = data[lastarr[nNo], arr[nNo], i];
            }

            return result;
        }
#endregion


#region 获取类型
        public static ThreeDistribution GetThreDis(double dPercent)
        {
            ThreeDistribution dis = ThreeDistribution.EN_THREEDIS_BAD;
            if (dPercent <= 0.15)
            {
                dis = ThreeDistribution.EN_THREEDIS_GOOD;
            }
            else if (dPercent <= 0.25)
            {
                dis = ThreeDistribution.EN_THREEDIS_LITTLE_GOOD;
            }
            else if (dPercent <= 0.4)
            {
                dis = ThreeDistribution.EN_THREEDIS_NORMAL;
            }
            else if (dPercent <= 0.5)
            {
                dis = ThreeDistribution.EN_THREEDIS_LITTLE_NORMAL;
            }
            else if (dPercent <= 0.75)
            {
                dis = ThreeDistribution.EN_THREEDIS_LITTLE_BAD;
            }
            else if (dPercent <= 1)
            {
                dis = ThreeDistribution.EN_THREEDIS_BAD;
            }
            else
            {
                dis = ThreeDistribution.EN_THREEDIS_BAD;
            }

            return dis;
        }
#endregion


    }

#region 指标定义

    /// <summary>
    /// 组三的分布情况
    /// </summary>
    public enum ThreeDistribution
    {
        EN_THREEDIS_GOOD,                           // 0-15%
        EN_THREEDIS_LITTLE_GOOD,                    // 16%-25%
        EN_THREEDIS_NORMAL,                         // 26%-40%
        EN_THREEDIS_LITTLE_NORMAL,                  // 40%-50&
        EN_THREEDIS_LITTLE_BAD,                     // 51%-75%
        EN_THREEDIS_BAD                             // 76%-100%
    }

    /// <summary>
    /// 周期的定义
    /// </summary>
    public class PeriodInfo
    {
        public PeriodInfo(double ave, double off)
        {
            dAveragePeriod = ave;
            dAverageOffPeriod = off;
            dTotalPeriod = dAveragePeriod + dAverageOffPeriod;
        }

        // 平均周期
        public double dAveragePeriod = 0;

        // 平均的偏移周期
        public double dAverageOffPeriod = 0;

        public double dTotalPeriod = 0;
    }
    

    /// <summary>
    /// 20为基本单元时候的指标
    /// </summary>
    public class UintParam
    {
        // 组态的中三种类型的个数
        public Dictionary<CombinationState, int> CombinationCount;

        // 组三的分布
        public ThreeDistribution ThreeDis;

        // 百分比
        public Dictionary<CombinationState, double> CombinationPercent;

        public UintParam()
        {
            // 组态个数
            CombinationCount = new Dictionary<CombinationState, int>();
            CombinationCount.Add(CombinationState.EN_COM_THREE, 0);
            CombinationCount.Add(CombinationState.EN_COM_SIX, 0);
            CombinationCount.Add(CombinationState.EN_COM_ALL, 0);

            CombinationPercent = new Dictionary<CombinationState, double>();
            CombinationPercent.Add(CombinationState.EN_COM_THREE, 0);
            CombinationPercent.Add(CombinationState.EN_COM_SIX, 0);
            CombinationPercent.Add(CombinationState.EN_COM_ALL, 0);

            ThreeDis = ThreeDistribution.EN_THREEDIS_BAD;
        }

        /// <summary>
        /// 通过三个组合构建
        /// </summary>
        /// <param name="nSix"></param>
        /// <param name="nThree"></param>
        /// <param name="nAll"></param>
        public UintParam(int nSix, int nThree, int nAll)
        {
            double dTotal = (double)(nThree + nAll + nSix);

            // 组态个数
            CombinationCount = new Dictionary<CombinationState, int>();
            CombinationCount.Add(CombinationState.EN_COM_SIX, nSix);
            CombinationCount.Add(CombinationState.EN_COM_THREE, nThree);
            CombinationCount.Add(CombinationState.EN_COM_ALL, nAll);

            CombinationPercent = new Dictionary<CombinationState, double>();
            CombinationPercent.Add(CombinationState.EN_COM_SIX, (nSix) / dTotal);
            CombinationPercent.Add(CombinationState.EN_COM_THREE, (nThree) / dTotal);
            CombinationPercent.Add(CombinationState.EN_COM_ALL, (nAll) / dTotal);

            ThreeDis = LotteryComPerdictor.GetThreDis((nThree + nAll) / dTotal);
        }

        public CombinationState GetMaxCom()
        {
            int nSix = CombinationCount[CombinationState.EN_COM_SIX];
            int nThree = CombinationCount[CombinationState.EN_COM_THREE];
            int nAll = CombinationCount[CombinationState.EN_COM_ALL];
             
            // 得到最大值
            int nMax = Math.Max(nSix, Math.Max(nThree, nAll));

            if (nSix == nMax)
            {
                return CombinationState.EN_COM_SIX;
            }
            else if (nThree == nMax)
            {
                return CombinationState.EN_COM_THREE;
            }
            else if (nAll == nMax)
            {
                return CombinationState.EN_COM_ALL;
            }

            return CombinationState.EN_COM_THREE;
        }
    }

    /// <summary>
    /// 最后三位中，各个数字个数的统计（不针对某一位，三个合一起）
    /// </summary>
    public class ThreeNumerialParam
    {
        // 统计的个数
        public int nCount = 0;

        // 0-9 数字出现的个数
        public int[] PerCount= new int[10];

        // 从小到大排序后的数字
        public int[] Sort()
        {
            List<int> list = PerCount.ToList();
            int[] sortResult = new int[10];

            // 加入到一个结构体中
            List<Uint> temps = new List<Uint>();
            for (int i = 0; i < PerCount.Length; i++)
            {
                Uint temp = new Uint();
                temp.nNo = i;
                temp.value = PerCount[i];
                temps.Add(temp);
            }

            // 冒泡排序
            for (int i = temps.Count; i > 0; i--)
            {
                for (int j = 0; j < i - 1; j++)
                {
                    if (temps[j].value > temps[j + 1].value)
                    {
                        Uint temp = temps[j];
                        temps[j] = temps[j + 1];
                        temps[j + 1] = temp;
                    }
                }
            }

            // 放到结果中去
            for (int i = 0; i < temps.Count; i++)
            {
                sortResult[i] = temps[i].nNo;
            }

            // 返回
            return sortResult;
        }

        private class Uint
        {
            public int nNo;
            public int value;
        }
    }

    /// <summary>
    /// 一定个数的结果
    /// </summary>
    public class CommonReuslt
    {
        // 总个数
        public int nCount = 0;

        // 总个数中参与投入的个数
        public int nValidCount = 0;

        // 最大投入金额
        public double dMaxCost = 0;

        // 组六个数
        public int nSix = 0;

        // 正确个数
        public int nRight = 0;

        // 经过nCount次后，得到的总金额
        public double dTotal = 0;

        // 正确比
        public double dRightPercent = 0;
    }
    
#endregion


}
